// Package cobraapi 定义一个 server的子命令，用于启动 http服务
package cobraapi

import (
	"context"
	"github.com/spf13/cobra"
	"net/http"
	"os"
	"os/signal"
	"time"
	"tyjt-ferry/database"
	"tyjt-ferry/database/orm"
	"tyjt-ferry/internal/config"
	"tyjt-ferry/internal/web"
	"tyjt-ferry/pkg/logger"
)

var (
	configPath string
	port       string
	mode       string
	StartCmd   = &cobra.Command{
		Use:     "server",
		Short:   "Start API server",
		Example: "ferry server config/settings.yaml",
		PreRun: func(cmd *cobra.Command, args []string) {
			setup()
		},
		RunE: func(cmd *cobra.Command, args []string) error {
			return run2()
		},
	}
)

func init() {
	StartCmd.PersistentFlags().StringVarP(&configPath, "config", "c", "config/config.yaml", "Start server with provided configuration file")
	StartCmd.PersistentFlags().StringVarP(&port, "port", "p", "8004", "Tcp port server listening on")
	StartCmd.PersistentFlags().StringVarP(&mode, "mode", "m", "dev", "server mode ; eg:dev,test,prod")
}

func setup() {
	// 加载配置
	config.ConfigSetup(configPath)

	// 数据库初始化
	database.Setup()
	//database.SetupIOC()
	//
}

func run() error {
	r := web.InitRouter()

	addr := config.ApplicationConfig.Host + ":" + config.ApplicationConfig.Port
	srv := &http.Server{
		Addr:    addr,
		Handler: r,
	}

	// 数据库关闭
	defer func() {
		err := orm.Eloquent.Close()
		if err != nil {
			logger.Error(err)
		}
	}()

	go func() {
		// 启动服务监听
		logger.Infof("http 服务启动监听成功，地址是 %s", addr)
		err := srv.ListenAndServe()
		if err != nil {
			logger.Errorf("http 服务启动监听失败： %v", err)
		}
	}()

	// 等待终端信号，优雅的关闭服务器
	quit := make(chan os.Signal)
	// 注册监听信号,一旦程序收到用户中断（Ctrl+C）信号，它就会把信号发送到 quit 通道
	signal.Notify(quit, os.Interrupt)
	// 主协程会 阻塞在这里等待信号，直到收到了中断信号，才会继续往下执行
	<-quit
	// 创建一个带有 5 秒超时的上下文 ctx，用于控制后续 srv.Shutdown(ctx) 的最大等待时间
	ctx, cancle := context.WithTimeout(context.Background(), 5*time.Second)
	defer cancle()
	// srv.Shutdown(ctx) 是 http.Server 提供的优雅关闭方法：
	//它会等待当前所有正在处理的请求完成；同时拒绝新的连接
	if err := srv.Shutdown(ctx); err != nil {
		logger.Fatalf("程序关闭失败 %v", err)
	}
	logger.Info("程序正常关闭。。。")

	return nil
}

func run2() error {
	r := web.InitRouter()
	addr := config.ApplicationConfig.Host + ":" + config.ApplicationConfig.Port
	logger.Infof("http 服务启动监听成功，地址是 %s", addr)
	err := r.Run(addr)
	if err != nil {
		logger.Errorf("http 服务启动监听失败： %v", err)
		return err
	}

	// 数据库关闭
	defer func() {
		err := orm.Eloquent.Close()
		if err != nil {
			logger.Error(err)
		}
	}()

	return nil
}
